package com.xmall.sys.service.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.xmall.define.base.ResultCode;
import com.xmall.exception.XmallException;
import com.xmall.sys.define.dto.role.SysRoleDto;
import com.xmall.sys.define.request.role.RoleListPageQueryRequest;
import com.xmall.sys.define.request.role.RolePermissionUpdateRequest;
import com.xmall.sys.define.request.role.RoleQueryRequest;
import com.xmall.sys.define.request.role.RoleUpdateRequest;
import com.xmall.sys.entity.Role;
import com.xmall.sys.entity.RolePermission;
import com.xmall.sys.entity.UserRole;
import com.xmall.sys.mapper.RoleMapper;
import com.xmall.sys.service.IRolePermissionService;
import com.xmall.sys.service.IRoleService;
import com.xmall.sys.service.IUserRoleService;
import com.xmall.sys.utils.ConvertUtils;
import com.xmall.utils.XmallUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

@Service
public class RoleServiceImpl extends ServiceImpl<RoleMapper, Role> implements IRoleService {

    @Resource
    private IRolePermissionService rolePermissionService;

    @Resource
    private IUserRoleService userRoleService;

    /**
     * 详情
     */
    @Override
    public SysRoleDto info(Long id) {
        return ConvertUtils.RoleModule.INSTANCE.toDto(this.getById(id));
    }

    /**
     * 列表
     */
    @Override
    public List<SysRoleDto> list(RoleQueryRequest request) {
        QueryWrapper<Role> query = new QueryWrapper<>();
        query.like(StrUtil.isNotBlank(request.getName()), "name", request.getName());

        return ConvertUtils.RoleModule.INSTANCE.toDtoList(this.list(query));
    }

    /**
     * 分页列表
     */
    @Override
    public Page<SysRoleDto> listPage(RoleListPageQueryRequest request) {
        Page<SysRoleDto> result = new Page<>();

        //查询条件
        QueryWrapper query = new QueryWrapper();
        query.like(StrUtil.isNotBlank(request.getName()), "name", request.getName());

        //分页
        Page<Role> page = this.page(new Page(request.getPage(), request.getPageSize()), query);

        //转换属性
        BeanUtils.copyProperties(page, result);
        result.setRecords(ConvertUtils.RoleModule.INSTANCE.toDtoList(page.getRecords()));
        return result;
    }

    /**
     * 新增
     */
    @Override
    public void saveEntity(RoleUpdateRequest request) {
        checkRepeat(request);
        this.save(ConvertUtils.RoleModule.INSTANCE.toEntity(request));
    }

    /**
     * 编辑
     */
    @Override
    public void updateEntity(RoleUpdateRequest request) {
        Role entity = this.getById(request.getId());
        XmallUtils.notNull(entity);

        if(null != entity && !Objects.equals(request.getName(), entity.getName())){
            checkRepeat(request);
        }

        this.updateById(ConvertUtils.RoleModule.INSTANCE.toEntity(request));
    }

    /**
     * 更新角色关联的权限列表
     */
    @Transactional
    @Override
    public void updateRolePermission(RolePermissionUpdateRequest request) {
        //删除之前所有关联关系
        rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", request.getRoleId()));
        //新增关联关系列表
        List<RolePermission> updateList = request.getPermissionIds().stream().map(permissionId -> {
            RolePermission entity = new RolePermission();
            entity.setRoleId(request.getRoleId());
            entity.setPermissionId(permissionId);
            return entity;
        }).collect(Collectors.toList());
        rolePermissionService.saveBatch(updateList);
    }

    /**
     * 角色关联的权限ID列表
     */
    @Override
    public List<Long> rolePermissionIds(Long roleId) {
        List<RolePermission> rolePermissionList = rolePermissionService.list(new QueryWrapper<RolePermission>().eq("role_id", roleId));
        if(CollectionUtil.isEmpty(rolePermissionList)){
            return new ArrayList<>();
        }
        return rolePermissionList.stream().map(entity -> entity.getPermissionId()).collect(Collectors.toList());
    }

    /**
     * 删除
     */
    @Transactional
    @Override
    public void deleteEntity(Long id) {
        //如果角色被用户关联，不允许删除
        List<UserRole> userRoleList = userRoleService.list(new QueryWrapper<UserRole>().eq("role_id", id));
        if(null != userRoleList && userRoleList.size() > 0){
            throw new XmallException(ResultCode.SYS_ROLE_HAS_RELATION_TO_USER);
        }

        Role role = this.getById(id);
        if(null != role){
            //删除角色
            this.removeById(role);
            //删除角色权限关联
            rolePermissionService.remove(new QueryWrapper<RolePermission>().eq("role_id", id));
        }
    }

    /**
     * 角色名称是否已存在
     */
    private void checkRepeat(RoleUpdateRequest request){
        QueryWrapper query = new QueryWrapper<Role>().eq("name", request.getName());
        if(null != this.getOne(query)){
            throw new XmallException(ResultCode.SYS_ROLE_NAME_EXIST);
        }
    }
}
